"""Shared utility functions for API endpoints."""

from __future__ import annotations

from datetime import datetime
from typing import Any
from uuid import UUID

from fastapi import status
from fastapi.responses import JSONResponse

from app.core.errors import format_response


def _serialize(data: Any) -> Any:
    """Recursively serialize data for JSON response.

    Handles:
    - Lists and dicts (recursive)
    - datetime objects → ISO format strings
    - UUID objects → strings
    - Pydantic models → model_dump()

    Args:
        data: Data to serialize

    Returns:
        JSON-serializable data
    """
    if isinstance(data, list):
        return [_serialize(item) for item in data]
    if isinstance(data, dict):
        return {key: _serialize(value) for key, value in data.items()}
    if isinstance(data, datetime):
        return data.isoformat()
    if isinstance(data, UUID):
        return str(data)
    if hasattr(data, "model_dump"):
        return _serialize(data.model_dump())
    return data


def _ok(data: Any, message: str = "success", code: int = status.HTTP_200_OK) -> JSONResponse:
    """Create a successful JSON response with standardized format.

    Args:
        data: Response data to serialize
        message: Success message (default: "success")
        code: HTTP status code (default: 200)

    Returns:
        JSONResponse with format: {"code": 200, "message": "success", "data": {...}}
    """
    return JSONResponse(status_code=code, content=format_response(code, message, _serialize(data)))


def _err(message: str, code: int = status.HTTP_400_BAD_REQUEST, data: Any = None) -> JSONResponse:
    """Create an error JSON response with standardized format.

    Args:
        message: Error message
        code: HTTP status code (default: 400)
        data: Optional error details

    Returns:
        JSONResponse with format: {"code": 400, "message": "error", "data": null}
    """
    return JSONResponse(status_code=code, content=format_response(code, message, _serialize(data) if data else None))
